import { useState, useEffect, useRef } from "react";
import { Text, View, StyleSheet, TextInput, Pressable } from "react-native";
import Btn from "@/components/Btn";
import WebSocketOperator from "@anlib/websocket-operator";
import NetworkState from "@/components/NetworkState";
import { useSelector } from "react-redux";
import type { RootState } from "@/store";
import dayjs from "dayjs";
import { FlashList } from "@shopify/flash-list";

let wsOperator: WebSocketOperator | null = null;

const System = () => {
  const [state, _setState] = useState({
    /** websocket 连接地址 */
    // wsServeUrl: config.wsServeUrl,
    wsServeUrl: "",
    /** 消息 */
    input: "",
    /** 是否连接 */
    isConnect: false,
    /** 服务端返回的消息 */
    msg: [] as string[],
    /** 错误消息 */
    error: ""
  });

  // 通用更新状态单个
  const setState = (field: keyof typeof state, val: any) => {
    _setState(_state => {
      return { ..._state, [field]: val };
    });
  };

  // 通用更新状态(对象)
  const setObjState = (obj: Partial<typeof state>) => {
    _setState(_state => {
      return { ..._state, ...obj };
    });
  };

  const flashListRef = useRef<FlashList<any>>(null);
  const networkState = useSelector((state: RootState) => state.common.networkState);

  const setMsg = (val: string[]) => {
    const newMsg = val.map(e => `${dayjs().format("HH:mm:ss")}: ${e}`);
    _setState(state => {
      return {
        ...state,
        msg: [...state.msg, ...newMsg]
      };
    });

    if (flashListRef.current) {
      flashListRef.current.scrollToEnd({
        animated: true
      });
    }
  };

  const connect = () => {
    WebSocketOperator.isCompatibleWebSocket()
      .then(() => {
        setMsg(["开始连接"]);
        wsOperator = new WebSocketOperator({
          url: state.wsServeUrl,
          heartbeatInterval: 1000, // 心跳间隔
          heartbeatData: "ping", // 心跳回应数据, 需要配合 heartbeatResult
          heartbeatResult: "pone", // 服务端心跳回应的值
          reconnectInterval: 1000, // 重试间隔
          // maxReconnectionNum: -1, // 无限重试
          maxReconnectionNum: 5,
          isSpeedUp: false // 不会重试加快
        });

        // 发送心跳时触发
        wsOperator.onheartbeat = params => {
          const tip = `正在发送第${params.heartbeatNum}次心跳: ${wsOperator?.heartbeatData}`;
          console.log(tip, params);
          setMsg([tip]);
        };

        // 重新连接时触发
        wsOperator.onreconnection = params => {
          console.log("重新连接: ", params);
          setMsg(["重新连接"]);
        };

        // 错误重试达到最大时触发
        wsOperator.onmaxReconnection = params => {
          const tip = `错误重试达到最大(${params.reconnectionNum}): `;
          console.log(tip, params);
          setMsg([tip]);
        };

        // 销毁时触发
        wsOperator.ondestroy = params => {
          console.log("销毁: ", params);
          setMsg(["销毁"]);

          wsOperator = null;
          setObjState({
            error: "",
            isConnect: false
          });
        };

        // 原本 WebSocket 的事件
        wsOperator.onmessage = params => {
          console.log("服务端返回数据: ", params);
          const e = params.event as WebSocketMessageEvent;
          setMsg([`服务端返回数据: ${e.data}`]);
        };

        wsOperator.onopen = params => {
          console.log("连接成功: ", params);
          setState("isConnect", true);
          setMsg(["连接成功"]);
        };
        // wsOperator.onclose = params => {
        //   console.log("onclose: ", params);
        // };
        wsOperator.onerror = params => {
          console.log("连接错误: ", params);

          const e = params.event as WebSocketErrorEvent;
          setMsg(["连接错误"]);

          setObjState({
            isConnect: false,
            error: e.message
          });
        };

        // 关闭
        // wsOperator.close();
      })
      .catch(err => {
        console.log("err: ", err);
        setMsg(["你的设备不支持 WebSocket"]);
      });
  };

  const breakConnect = () => {
    if (wsOperator) wsOperator.destroy();
  };

  const sendData = () => {
    if (wsOperator) {
      wsOperator.send(state.input);
      setState("input", "");
      setMsg([`发送数据: ${state.input}`]);
    }
  };

  useEffect(() => {
    () => {
      breakConnect();
    };
  }, []);

  return (
    <View>
      <View>
        <Text style={styles.title}>WebScoket</Text>
        <View style={styles.item}>
          <View style={[styles.item, { backgroundColor: "green" }]}>
            <Text style={{ color: "#fff" }}>网络状态: </Text>
            <NetworkState state={networkState ? "3" : "1"} content="有网" />
            <Text style={{ color: "#fff" }}>{state.isConnect ? "已连接" : "未连接"}</Text>
          </View>
          <TextInput
            style={styles.input}
            placeholder="请输入websocket地址"
            onChangeText={text => setState("wsServeUrl", text)}
            value={state.wsServeUrl}
          />
          <Btn text="连接" type="primary" onClick={connect} disabled={state.isConnect} />
          <Btn text="断开" type="danger" onClick={breakConnect} disabled={!state.isConnect} />
          <Btn text="清空日志" type="warning" onClick={() => setState("msg", [])} />
        </View>
      </View>
      <View style={styles.item}>
        <TextInput
          style={styles.input}
          placeholder="请输入消息"
          onChangeText={text => setState("input", text)}
          value={state.input}
        />
        <Btn text="发送消息" type="primary" onClick={sendData} disabled={!state.isConnect} />
      </View>
      {state.error && <Text style={{ color: "red" }}>错误信息: {state.error}</Text>}
      <Text>日志如下: </Text>
      <View style={styles.scrollView}>
        <FlashList
          data={state.msg}
          ref={flashListRef}
          estimatedItemSize={50}
          renderItem={({ item, index }) => {
            return (
              <Pressable>
                <Text style={{ height: 20 }}>
                  {index + 1}. {item}
                </Text>
              </Pressable>
            );
          }}
        />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  title: { fontSize: 28, textAlign: "center" },
  item: {
    margin: 10,
    display: "flex",
    alignItems: "center",
    flexDirection: "row",
    gap: 10
  },
  dividerGap: {
    height: 10,
    marginBottom: 10
  },
  scrollView: {
    height: 200,
    width: 400,
    borderColor: "green",
    borderWidth: 1,
    borderStyle: "solid",
    borderRadius: 4
  },
  input: {
    height: 40,
    minWidth: 250,
    borderColor: "gray",
    borderWidth: 1,
    borderRadius: 4,
    paddingLeft: 10
  }
});

export default System;
